#include "all2.h"
#include "MatriceDesPossibles.h"
#include <math.h>

MatriceDesPossibles::MatriceDesPossibles(vector<Piece> lp, int taille){

    //INITIALISATION

    matrice.resize(lp.size()*4);
    int tailley = pow(taille*2 +1,2);
    //vector<Po> lpo; //liste des pieces orientés.
    for(int i=0; i < lp.size(); i++){
        lp[i].estPose= false; //EstPosé est réutilisé comme le droit que la piece soit posé à cet endroit.
    }
    lpo.resize(lp.size() * 4);
    for(int i =0; i<lp.size(); i++){
        lpo[i].p = lp[i];
        lpo[i].orient = 0;
    }
    for(int i =0; i<lp.size(); i++){
        lpo[i + lp.size()].p = lp[i];
        lpo[i + lp.size()].orient = 1;
    }
    for(int i =0; i<lp.size(); i++){
        lpo[i + 2*lp.size()].p = lp[i];
        lpo[i + 2*lp.size()].orient = 2;
    }
    for(int i =0; i<lp.size(); i++){
        lpo[i + 3*lp.size()].p = lp[i];
        lpo[i + 3*lp.size()].orient = 3;
    }

    cout<<"Matrice des possible de taille : "<<taille<<" : "<<lp.size()*4<<" - "<<tailley<<" - "<<lpo.size()<<endl;
    for(int i = 0;i<matrice.size(); i++){
        matrice[i].resize(tailley);
    }
    for(int i = 0;i<matrice.size(); i++){
        for(int j = 0;j<matrice[i].size(); j++){
            matrice[i][j] = lpo;
        }
    }
    cout<<"ok :-)"<<endl;
    cout<<"cti"<<coordToInt(0,1)<<endl;
    cout<<"cti"<<coordToInt(1,0)<<endl;
    cout<<"cti"<<coordToInt(0,-1)<<endl;
    cout<<"cti"<<coordToInt(-1,0)<<endl;
    //cout<<"tailles : "<<

    //REMPLISSAGE DE LA MATRICE
    Piece pTemp; //piece temporaire selectionnée itérativement par la boucle principale.
    Piece pTemp2; //piece temporaire selectionnée itérativement par les sous boucles.
    Piece pTemp3; //piece temporaire selectionnée itérativement par les sous-sous boucles.
    //Piece pTemp = poToPiece(intToPo(i));


    for(int i=0; i<matrice.size(); i++){
        pTemp = poToPiece(intToPo(i));
        // I : Identité :

        // II : Voisins directs :
        //on verifie d'abord que les cotés sont compatibles nv couleur et qu'ils ne sont pas la meme piece.
        for(int j=0; j<matrice.size(); j++){
            pTemp2 = poToPiece(intToPo(j));
            if( pTemp.numero != pTemp2.numero){
                if(pTemp.haut == pTemp2.bas && pTemp.haut !=0){ //verifie que haut d'une piece = bas de l'autre.
                    matrice[i][coordToInt(0,-1)][j].p.estPose = true;
                }
                if(pTemp.bas == pTemp2.haut && pTemp.bas !=0){ //verifie que bas d'une piece = haut de l'autre.
                    matrice[i][coordToInt(0,1)][j].p.estPose = true;
                }
                if(pTemp.droit == pTemp2.gauche && pTemp.droit !=0){ //verifie que droit d'une piece = gauche de l'autre.
                    matrice[i][coordToInt(1,0)][j].p.estPose = true;
                }
                if(pTemp.gauche == pTemp2.droit && pTemp.gauche !=0){ //verifie que gauche  d'une piece = droit de l'autre.
                    matrice[i][coordToInt(-1,0)][j].p.estPose = true;
                }

                if(pTemp.haut==0 && pTemp2.haut!=0 || pTemp.haut!=0 && pTemp2.haut==0 || pTemp.bas!=0 && pTemp2.bas==0 || pTemp.bas==0 && pTemp2.bas!=0 ){
                    matrice[i][coordToInt(1,0)][j].p.estPose = false;
                    matrice[i][coordToInt(-1,0)][j].p.estPose = false;
                }
                if(pTemp.gauche!=0 && pTemp2.gauche==0 || pTemp.gauche==0 && pTemp2.gauche!=0 || pTemp.droit!=0 && pTemp2.droit==0 || pTemp.droit==0 && pTemp2.droit!=0){
                    matrice[i][coordToInt(0,1)][j].p.estPose = false;
                    matrice[i][coordToInt(0,-1)][j].p.estPose = false;
                }
            }
        }


    cout<<"OK, on passe aux diagonales!"<<endl;

                //OK, on passe aux diagonales!
                //Précalcul des cases possibles autours.
                vector<Po> vTempG = poPossibles(matrice[i][coordToInt(-1,0)]);
                cout<<"vTempG"<<endl;
                cout<<vTempG.size()<<endl;
                //cout<<vTempG[0].p<<endl;
                vector<Po> vTempD = poPossibles(matrice[i][coordToInt(1,0)]);
                vector<Po> vTempH = poPossibles(matrice[i][coordToInt(0,-1)]);
                vector<Po> vTempB = poPossibles(matrice[i][coordToInt(0,1)]);
                bool bH, bB, bG, bD; //Servent à vérifier que les pieces donnent bien des pieces compatibles...
                /*bH1= false;
                bB1= false;
                bG1= false;
                bD1= false;
                bH2= false;
                bB2= false;
                bG2= false;
                bD2= false; */
                cout<<"premiere diagonale : haut gauche : "<<endl;
                if(vTempG.size()>0 && vTempH.size()>0){
                    cout<<"."<<endl;
                    for(int j=0; j<vTempG.size(); j++){
                        cout<<".."<<j<<endl;
                        cout<<vTempG[j].p<<endl;
                        pTemp2 = poToPiece(vTempG[j]);
                        cout<<"..."<<endl;
                        for(int k=0; k<vTempH.size(); k++){
                            pTemp3 = poToPiece(vTempH[k]);
                            for(int l=0; l<lpo.size(); l++){
                                //cout<<"for interieur max"<<endl;
                                //cout<<poToPiece(intToPo(l))<<" - "<<poToPiece(intToPo(l))<<endl;
                                if(pTemp2.haut == poToPiece(intToPo(l)).bas && pTemp3.gauche == poToPiece(intToPo(l)).droit ){
                                    matrice[i][coordToInt(-1,-1)][l].p.estPose = true;
                                }
                            }
                        }
                    }
                }
                cout<<"deuxieme diagonale : haut droit : "<<endl;
                if(vTempD.size()>0 && vTempH.size()>0){
                    for(int j=0; j<vTempD.size(); j++){
                        pTemp2 = poToPiece(vTempD[j]);
                        for(int k=0; k<vTempH.size(); k++){
                            pTemp3 = poToPiece(vTempH[k]);
                            for(int l=0; l<lpo.size(); l++){
                                if(pTemp2.haut == poToPiece(intToPo(l)).bas && pTemp3.droit == poToPiece(intToPo(l)).gauche ){
                                   matrice[i][coordToInt(1,-1)][l].p.estPose = true;
                                }
                            }
                        }
                    }
                }
                if(vTempG.size()>0 && vTempB.size()>0){
                    for(int j=0; j<vTempB.size(); j++){
                        pTemp2 = poToPiece(vTempG[j]);
                        for(int k=0; k<vTempB.size(); k++){
                            pTemp3 = poToPiece(vTempB[k]);
                            for(int l=0; l<lpo.size(); l++){
                                if(pTemp2.bas == poToPiece(intToPo(l)).haut && pTemp3.gauche == poToPiece(intToPo(l)).droit ){
                                   matrice[i][coordToInt(-1,1)][l].p.estPose = true;
                                }
                            }
                        }
                    }
                }
                if(vTempD.size()>0 && vTempB.size()>0){
                    for(int j=0; j<vTempD.size(); j++){
                        pTemp2 = poToPiece(vTempD[j]);
                        for(int k=0; k<vTempB.size(); k++){
                            pTemp3 = poToPiece(vTempB[k]);
                            for(int l=0; l<lpo.size(); l++){
                                if(pTemp2.bas == poToPiece(intToPo(l)).haut && pTemp3.droit == poToPiece(intToPo(l)).gauche ){
                                   matrice[i][coordToInt(1,1)][l].p.estPose = true;
                                }
                            }
                        }
                    }
                }
                /* else {
                    for(int j=0; i<matrice.size(); j++){
                        matrice[i][coordToInt(-1,-1)][j].p.estPose = false;
                    }
                } */
            }

}


vector<Po> MatriceDesPossibles::poPossibles(vector<Po> vecteur){
    vector <Po> vecRetour;
    for(int i =0; i<vecteur.size(); i++){
        if(vecteur[i].p.estPose == true){
            vecRetour.push_back(vecteur[i]);
        }
    }
    return vecRetour;
}


Po MatriceDesPossibles::intToPo(int i){
    /*Po pTemp;
    //pTemp.orient = i / (matrice.size()/4);
    //pTemp.p = lpo[i % (matrice.size()/4)];
    pTemp = lpo[i];
    return pTemp;
    */
    return lpo[i];
}

int MatriceDesPossibles::poToInt(Po pieceOriente){ //retourne lke numero de case correspondant à la case ou la Po est stocké.
    /*int r;
    r = pieceOriente.p.numero + matrice.size()* pieceOriente.orient;
    return r;
    */
    return pieceOriente.p.numero-1 + lpo.size()/4* pieceOriente.orient;
}

int MatriceDesPossibles::coordToInt(Coord c){
    return coordToInt(c.x,c.y);
}


int MatriceDesPossibles::coordToInt(int x, int y){
    int tailleTab=sqrt( matrice[0].size());
    return ((tailleTab+y)*tailleTab+tailleTab+x) -matrice[0].size() +1;
}

vector<Po> MatriceDesPossibles::getLpo(){
    return lpo;
}

vector<Po> MatriceDesPossibles::vpo(Po piece, Coord c){
    return matrice[poToInt(piece)][coordToInt(c)];
 }
